home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PD Collection CD 1
/
PD Collection CD 1.iso
/
programer2
/
pari2
/
pari
/
other
/
pari_el
< prev
next >
Wrap
Lisp/Scheme
|
1991-11-13
|
19KB
|
603 lines
;; This is the interface for pari under emacs
;; The main commands in this file are
;; M-x gp Opens a buffer for interaction with gp and then starts gp.
;; C-u M-x gp Like M-x gp, but prompts for command line arguments.
;; M-x gpman Displays the gp-pari manual using any dvi preview program.
;; All functions of gp are preserved.
;; This version by David Carlisle (JANET: carlisle@uk.ac.man.cs).
;; The original pari.el was written by Annette Hoffman.
;; Version 2.8 (22/4/91)
;; See pari.txt for more details.
(provide 'gp)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The following five constants (aka variables !) should be
;; set for each site.
(defconst gp-chap3 "~pari/PARISOURCES/tex/usersch3.tex"
"The TeX source for chapter 3 of the PARI-GP manual")
(defconst gp-file-name "/usr/local/bin/gp"
"The file name of the gp executable file")
(defconst gp-man-dvi "~pari/SPARC/tex/users.dvi"
"dvi version of the manual")
(defconst gp-menu "~pari/PARISOURCES/pari.menu"
"menu file")
(defconst gp-dvi-preview "xdvi -s 3"
;; (defconst gp-dvi-preview "texsun"
"dvi previewer (and options)")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Individual users may want re-set some of the variables in this section
;; in a gp-mode-hook in their .emacs file.
;; See pari.txt for an example of a gp-mode-hook.
(defvar gp-stack-size "4000000"
"Default stack size: passed to the progam gp.")
(defvar gp-buffer-size "30000"
"Default buffer size: passed to the progam gp.")
(defvar gp-prime-limit "500000"
"Default prime limit: passed to the progam gp.")
(defvar gp-prompt-for-args nil
"A non-nil value makes M-x gp act like C-u M-x gp,
ie prompt for the command line arguments.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar gp-prompt-pattern
"---- (type return to continue) ----\\|\\?[\C-j\t ]*"
"Regexp used to match gp prompts.
can be set with gp-set-prompt (bound to M-\\ p)")
(defvar gp-map (make-sparse-keymap)
"Local keymap used in buffer *PARI*.")
(define-key gp-map "\C-m" 'gp-send-input)
(define-key gp-map "\M-\C-m" 'gp-copy-input)
(define-key gp-map "\M-\\p" 'gp-set-prompt)
(define-key gp-map "\M-\\t" 'gp-meta-t)
(define-key gp-map "\M-\\d" 'gp-meta-d)
(define-key gp-map "\M-\\r" 'gp-meta-r)
(define-key gp-map "\M-\\w" 'gp-meta-w)
(define-key gp-map "\M-\\v" 'gp-meta-v)
(define-key gp-map "\M-\\x" 'gp-meta-x)
(define-key gp-map "\M-\\s" 'gp-meta-s)
(define-key gp-map "\M-\\b" 'gp-meta-b)
(define-key gp-map "\M-\\k" 'gp-meta-k)
(define-key gp-map "\M-\\q" 'gp-meta-q)
(define-key gp-map "\M-?" 'gp-get-man-entry)
(define-key gp-map "\M-\\c" 'gp-menu)
(define-key gp-map "\M-\\\\" 'gp-break-long-line)
(define-key gp-map "\C-c" 'gp-interrupt)
(defvar gp-process nil "")
(defvar gp-man-process nil "")
(defun gp (flag)
"
Open a buffer and a window for the execution of gp.
The following bindings are available:
\\{gp-map}
The variables
gp-file-name gp-stack-size gp-buffer-size gp-prime-limit
determine the command line that starts gp.
To override the default settings, give gp a prefix argument.
C-u M-x gp ."
(interactive "P")
;; Create buffer *PARI* and make it become the current buffer.
(switch-to-buffer "*PARI*")
(goto-char (point-max))
(if gp-process
nil
(kill-all-local-variables)
(setq major-mode 'gp)
(setq mode-name "GP")
;; Set up user preferences.
(run-hooks 'gp-mode-hook)
;; Make gp-map the local map of buffer *PARI*.
(use-local-map gp-map)
(setq mode-line-process '(": %s"))
;; Form the command line string.
(let* (
(flag (or flag gp-prompt-for-args))
(gp-command
(concat
(gp-read-input "Gp executable ?" gp-file-name "" flag)
(gp-read-input "Stack size ?" gp-stack-size " -s " flag)
(gp-read-input "Buffer size ?" gp-buffer-size " -b " flag)
(gp-read-input "Prime limit ?" gp-prime-limit " -p " flag))))
;; Insert the command line string into the *PARI* buffer.
;; (This is just for reference.)
(insert (concat "\n" gp-command "\n"))
;; Start gp.
(setq gp-process
(start-process
"pari" "*PARI*" shell-file-name "-c"
(concat "stty nl; exec " gp-command))))
;; Clean up when the gp process has finished.
(set-process-sentinel gp-process 'gp-sentinel)))
(defun gp-read-input (prompt default sep flag)
" If flag is non-nil, reads string then if string is \"\" uses default.
If flag is nil then string is the default.
If resulting string is not \"\" prepends sep.
As a special case, if string is a space, return \"\"."
(let ((string
(if flag
;; If flag is non-nil prompt for input from mini-buffer.
(read-input
(concat prompt " (Default "default") "))
;; Else use the default string.
default)))
(if (equal string "")
(if (equal default "")
;; If sting and default both "":
""
;; If string "" and default is non empty:
(concat sep default))
(if (equal string " ")
;; If string is a space:
""
;; If string is non empty:
(concat sep string)))))
(defun gp-sentinel (proc msg)
"Sentinel for the gp-process in buffer *PARI*."
(if (get-buffer "*PARI*")
(progn
(set-buffer "*PARI*")
(goto-char (point-max))
(insert msg)
(delete-windows-on "*PARI*")))
(if (get-buffer "*gp-help*") (kill-buffer "*gp-help*"))
(let ((b (get-file-buffer gp-chap3))) (if b (kill-buffer b)))
(let ((b (get-file-buffer gp-menu))) (if b (kill-buffer b)))
(if (file-exists-p gp-temp-file)
(progn (shell-command (concat "rm " gp-temp-file))
(message "Removing %s" gp-temp-file )))
(setq gp-process nil))
(defun gpman()
"Start up xdvi with the gp manual."
(interactive)
;; Run gp-mode-hook in case it specifies a different
;; version of the manual.
(run-hooks 'gp-mode-hook)
(set-buffer (get-buffer-create "*GP-MAN*"))
(if gp-man-process
nil
;; Start xdvi.
(message (concat "Starting " gp-dvi-preview " " gp-man-dvi))
(setq gp-man-process
(start-process "gp-man" "*GP-MAN*"
shell-file-name
"-c" (concat "exec " gp-dvi-preview " " gp-man-dvi)))
(set-process-sentinel gp-man-process 'gp-man-sentinel)))
(defun gp-man-sentinel (proc msg)
"Sentinel for the gp-man-process in buffer *GP-MAN*."
(let ((buf (process-buffer proc)))
(if buf (kill-buffer buf)))
(message (concat "gpman: " msg))
(setq gp-man-process nil))
(defun gp-copy-input()
"Copy expression around point to the end of the buffer.
(Unless this is already the last expression.)"
(interactive)
;; Go back to the end of prompt, and record that point.
;; If a line contains more than one prompt string, use the FIRST.
;; This is so that ? ?cos works. (ie gives the help for cos).
;; We can not insist on prompt at the beginning of a line (ie put
;; ^ in gp-prompt-pattern) because of the output from print1()
(re-search-backward gp-prompt-pattern)
(let ((p (match-end 0)))
(beginning-of-line)
(re-search-forward gp-prompt-pattern)
(setq gp-input-start (point))
;; Go past the last prompt on this line before looking for end of expression.
(goto-char p))
;; Check if we are already at the last expression.
(let ((nlast (re-search-forward (concat "[\n ]*\\("
gp-prompt-pattern
"\\|%[0-9]+ =\\|\\*\\*\\*\\|unused characters\\|time\\)")
(point-max) t)))
;; Find the limit of the expression.
;; This is the end of buffer,the prompt, or an error message.
(let ((limit (if nlast (match-beginning 0) (point-max))))
(goto-char gp-input-start)
;; End of expression is a line ending with } if it starts with {,
;; otherwise a line not ending with \.
(let ((end-expression (if (looking-at " *{") "}$" "[^\\]$")))
;; Look for the end of expression, as far as the limit computed above.
(setq gp-complete-expression (re-search-forward end-expression limit 1))
(setq gp-input-end (point))
;; If not already the last expression copy to the end of the buffer.
(if nlast
(progn
(goto-char (point-max))
(insert (buffer-substring gp-input-start gp-input-end))
(if gp-complete-expression
nil
(ding)
(message "Incomplete expression."))))))))
(setq gp-temp-file (make-temp-name "/usr/tmp/gp_"))
(defun gp-send-input ()
"Send input to gp. Does not send incomplete expressions
ie those starting with {, without a matching }, or those
ending with \\ .
Use a temporary file (and \\r ) for large expressions"
(interactive)
;; gp-copy-input does all the work!
(gp-copy-input)
(insert "\n")
(if gp-complete-expression
;; If it is a complete expression do this:
(progn
(if (> (- gp-input-end gp-input-start) 255)
;; If large expression, use a temporary file.
(progn
(write-region gp-input-start gp-input-end gp-temp-file)
(process-send-string gp-process (concat "\\r "gp-temp-file"\n")))
;; Else use process-send-region.
(process-send-region gp-process gp-input-start gp-input-end)
(process-send-string gp-process "\n"))
(set-marker (process-mark gp-process) (point)))
;; Else do this:
(message "Incomplete expression: Not sent to gp.")))
(defun gp-interrupt ()
"Interrupt gp.
This is identical to interrupt-shell-subjob in shell-mode."
(interactive)
(interrupt-process nil t))
(defun gp-set-prompt (p)
"Set new gp prompt (and tell emacs that you have done so).
Do not put spaces in the argument, or emacs and gp will
have a different idea about what the prompt is."
(interactive "sNew prompt: ")
;; gp-prompt-pattern matches:
;; (New prompt plus any following white space) OR (Old pattern).
(setq gp-prompt-pattern
(concat (regexp-quote p) "[\C-j\t ]*\\|" gp-prompt-pattern))
(set-buffer "*PARI*")
(goto-char (point-max))
;; Tell gp about the change too!
(insert (concat "\\prompt="p))
(gp-send-input))
(defun gp-replace (a b)
"Replace the regexp a by the string b everywhere in the current buffer"
(goto-char (point-min))
(while (re-search-forward a (point-max) t)
(replace-match b t t)))
(defun gp-get-man-entry (fn)
"Obtains the description of fn from chapter 3 of the manual.
Strips off some (not all) of the TeX syntax, and displays the result
in a new window.
If there is no entry for fn in the manual, sends ?fn to gp."
(interactive "sFunction: ")
;; Stop TeX-mode being loaded for gp-chap3.
(let ((auto-mode-alist nil))
(set-buffer (find-file-noselect gp-chap3)))
;; Fix up one or two special cases, or
;; regexp-quote the argument.
(let ((qfn (cond
((equal fn "\\" ) "\\\\backslash")
((equal fn "^" ) "\\\\hat{}")
((equal fn "!" ) "fact")
((equal fn "~" ) "trans")
((equal fn "_" ) "conj")
((equal fn "-" ) "\\+")
((equal fn "%" ) "\\\\%")
((equal fn "min" ) "max")
((equal fn "log" ) "ln")
((equal fn "det2" ) "det")
((or (equal fn "<=" )(equal fn "<" )(equal fn ">=" )
(equal fn ">" )(equal fn "==" )(equal fn "!=" )
(equal fn "||" )(equal fn "&&" ))
"comparison and \\\\ref{boolean operators}")
((regexp-quote fn)))))
;; Find the entry.
(goto-char (point-min))
;; Entry starts with \subsec ... fn
(if (re-search-forward
(concat "\\(subsec[\\\\{ref]*[\\${]\\)" qfn "[}\\$]") (point-max) t)
;; If There is an entry in the manual do this:
(progn
(goto-char (match-end 1))
(let ((copy (buffer-substring (point)
;; Entry ends with "The library" or the next (sub-)section.
(progn (re-search-forward "[tT]he library\\|\\\\[sub]*sec"
(point-max) t)
(match-beginning 0))))
(wind (selected-window)))
;; Copy the entry to the help buffer.
(switch-to-buffer-other-window (get-buffer-create "*gp-help*"))
(erase-buffer)
(insert copy)
;; Strip off some of the TeX. Note the idea is to leave enough
;; pseudo-TeX so that the entry is understandable. Thus want to
;; leave: a^2, x \over y, etc.
(gp-replace "\\$-" "-")
(gp-replace "\\$" " " )
(gp-replace "\\\\backslash" "\\")
(gp-replace "\\\\hat" "^")
(gp-replace
"\\\\smallskip\\|\\\\sref{[ a-z]*}\\|\\\\bf\\|\
\\\\ref\\|\\\\Bbb\\|\\\\text\\|\\\\tt\\|{\\|}"
"")
(goto-char (point-min))
(select-window wind)))
;; Else there is no entry in the manual. So send ?fn to gp.
(set-buffer "*PARI*")
(gp-meta-command (concat "?" fn)))))
(defun gp-meta-command (command)
"Send command to gp, and display output in help buffer"
(goto-char (point-max))
(let ((temp (point)) (wind (selected-window)))
;; Send the meta command to gp.
(process-send-string gp-process (concat command "\n"))
;; Wait for the gp-prompt to be sent.
(gp-wait-for-output)
;; Display the output in the help buffer.
(let ((copy (buffer-substring temp (point-max))))
(delete-region temp (point-max))
(switch-to-buffer-other-window (get-buffer-create "*gp-help*"))
(erase-buffer)
(insert copy)
(beginning-of-line)
(delete-region (point) (point-max))
(goto-char (point-min))
(select-window wind))))
(defun gp-wait-for-output ()
"Hang around until the prompt appears."
(setq ndone t)
(while ndone
(accept-process-output "*PARI*")
(let ((p (point)))
(beginning-of-line)
(if (looking-at gp-prompt-pattern)
(progn (message "done") (setq ndone nil))
(message "Waiting for gp output ..."))
(goto-char p))))
(defun gp-meta-d ()
"Sends \\d to gp, then displays output in the help buffer.
Prints the gp defaults."
(interactive)
(gp-meta-command "\\d"))
(defun gp-meta-t ()
"Sends \\t to gp, then displays output in the help buffer.
Prints the longword format of PARI types."
(interactive)
(gp-meta-command "\\t"))
(defun gp-meta-r (file)
"Sends a \\r <file name> comand to gp.
Reads in gp commands from a file.
See gp-meta-r"
(interactive "fRead from file: ")
(goto-char (point-max))
(insert (concat "\\r " (expand-file-name file)))
(gp-send-input))
(defun gp-meta-w (file num)
"Sends a \\w<num> <file name> comand to gp.
Writes gp object %<num> to <file name>."
(interactive "FWrite to file: \nsObject number %%")
(goto-char (point-max))
(insert (concat "\\w"num" " (expand-file-name file)))
(gp-send-input))
(defun gp-meta-x ()
"Sends \\x to gp, then displays output in the help buffer.
Prints tree of addresses and contents of last object."
(interactive)
(gp-meta-command "\\x"))
(defun gp-meta-v ()
"Sends \\v to gp, then displays output in the help buffer.
Prints the version number of this implementation of pari-gp."
(interactive)
(gp-meta-command "\\v"))
(defun gp-meta-s (num)
"Sends \\s or \\s(num) to gp, then displays output in the help buffer.
Prints the state of the pari stack."
(interactive "sNumber of longwords (default 0) ")
(if (equal num "")
(gp-meta-command "\\s")
(gp-meta-command (concat "\\s(" num ")" ))))
(defun gp-meta-b (num)
"Sends \\b or \\b<num> to gp, then displays output in the help buffer.
Prints object %<num> in pretty format (unless \\p set)."
(interactive "sPrint object (default last) %%")
(if (equal num "")
(gp-meta-command "\\b")
(gp-meta-command (concat "\\b" num))))
(defun gp-meta-k ()
"Sends \\k to gp.
Prompts for confirmation before
re-initialising gp and clearing the buffer."
(interactive)
(if (y-or-n-p "Re-initialise gp ? ")
(progn
(set-buffer "*PARI*")
(goto-char (point-max))
(insert "\\k\n")
(set-marker (process-mark gp-process) (point))
(if (y-or-n-p "Clear *PARI* buffer ? ")
(erase-buffer))
(process-send-string gp-process "\\k\n")))
(message ""))
(defun gp-meta-q ()
"Sends \\q to gp.
Prompts for confirmation before quiting."
(interactive)
(if (y-or-n-p "Quit gp ? ")
(progn
(set-buffer "*PARI*")
(goto-char (point-max))
(process-send-string gp-process "\\q\n")))
(message ""))
(defun gp-break-long-line ()
"gp will not accept lines longer than 256.
gp-break-long-lines breaks current line
inserting \\ every 100 chars."
(interactive)
(beginning-of-line)
(move-to-column 100)
(while (not (looking-at "$"))
(insert "\\\n")
(move-to-column 100)))
;;; The gp help mode.
(defun gp-menu ()
"Major-mode for the gp menu buffer.
The available commands are
\\{gp-menu-map}"
(interactive)
(find-file-other-window gp-menu)
(setq buffer-read-only t)
(kill-all-local-variables)
(setq major-mode 'gp-menu)
(setq mode-name "GP MENU")
(use-local-map gp-menu-map)
(gp-menu-main))
(defun gp-menu-info ()
(message "SPC=next DEL=previous RET=select m=main-menu q=quit s=scroll-help"))
(defun gp-menu-next ()
"Move down one line of the gp help menu. (Go to top if at the end.)"
(interactive)
(gp-menu-info)
(forward-line 1)
(if (eobp)
(progn (ding) (goto-char (point-min)))))
(defun gp-menu-previous ()
"Move up one line of the gp help menu. (Go to bottom if at the top.)"
(interactive)
(gp-menu-info)
(if (bobp)
(progn (ding) (goto-char (point-max)) (beginning-of-line))
(forward-line -1)))
(defun gp-menu-quit ()
"Switch the *PARI* buffer if it exists, or (other-buffer) if it does not."
(interactive)
(let ((w (get-buffer-window "*PARI*"))
(b (get-buffer "*PARI*")) )
(cond
(w (progn (delete-window)(select-window w)))
(b (switch-to-buffer b))
(t (switch-to-buffer (other-buffer))))))
(defun gp-menu-select ()
"Select a subject from the main menu, or a manual entry from a subject menu."
(interactive)
(if main-menu
;; RET in main menu.
(progn
(setq main-menu nil)
(widen)
(beginning-of-line)
(let ((sect (buffer-substring
(point) (progn (end-of-line) (point)))))
(narrow-to-region
(progn
(re-search-forward (concat "^###" sect))
(forward-line 1) (point))
(progn (re-search-forward "\C-j###" ) (match-beginning 0))))
(goto-char (point-min)))
;; RET in subject menu.
(beginning-of-line)
(gp-get-man-entry (buffer-substring
(point)
(progn (end-of-line) (point)))))
(gp-menu-info))
(defun gp-menu-main ()
"Display the main menu."
(interactive)
(gp-menu-info)
(widen)
(goto-char (point-min))
(narrow-to-region (point)
(progn (re-search-forward "\C-j###") (match-beginning 0)))
(goto-char (point-min))
(setq done nil)
(setq main-menu t))
(defun gp-menu-scroll ()
"Scroll the gp help window if it is visible"
(interactive)
(gp-menu-info)
(if (get-buffer-window "*gp-help*")
(let ((wind (selected-window)))
(switch-to-buffer-other-window "*gp-help*")
(if (pos-visible-in-window-p (point-max))
(goto-char (point-min))
(scroll-up))
(select-window wind))))
(defvar gp-menu-map (make-sparse-keymap)
"Local keymap used in gp menu buffer.")
(define-key gp-menu-map " " 'gp-menu-next)
(define-key gp-menu-map "\C-?" 'gp-menu-previous)
(define-key gp-menu-map "\C-m" 'gp-menu-select)
(define-key gp-menu-map "q" 'gp-menu-quit)
(define-key gp-menu-map "m" 'gp-menu-main)
(define-key gp-menu-map "s" 'gp-menu-scroll)